package com.lagou.sqlsession;

import com.lagou.pojo.Configuration;
import com.lagou.pojo.MapperStatement;

import java.beans.IntrospectionException;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

/**
 * @ClassName: DefaultSqlSession
 * @Description:
 * @Author: qiaojiacheng
 * @Date: 2021/7/22 2:34 下午
 */
public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        Executor executor = new SimpleExecutor();
        List<E> query = executor.query(configuration, mapperStatement, params);

        return query;
    }

    @Override
    public <T> T selectOne(String statementId, Object... params) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        Executor executor = new SimpleExecutor();
        List<Object> query = executor.query(configuration, mapperStatement, params);
        if (query.size() == 1) {
            return (T) query.get(0);
        } else {
            throw new RuntimeException("查询条数过多");
        }
    }

    @Override
    public int add(String statementId, Object... params) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        int result = executeUpdate(statementId, params);
        return result;
    }


    @Override
    public int delete(String statementId, Object... params) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        int result = executeUpdate(statementId, params);
        return result;
    }

    @Override
    public int update(String statementId, Object... params) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        int result = executeUpdate(statementId, params);
        return result;
    }

    private int executeUpdate(String statementId, Object[] params) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
        Executor executor = new SimpleExecutor();
        int update = executor.update(configuration, mapperStatement, params);
        return update;
    }

    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        T o = (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            /**
             *
             * @param proxy：当前代理对象的应用
             * @param method：当前被调用的方法
             * @param args：方法中传递的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 方法名
                String methodName = method.getName();
                // 全类名
                String className = method.getDeclaringClass().getName();
                // statementId
                String statementId = className + "." + methodName;
                // 获取返回值类型
                Type genericReturnType = method.getGenericReturnType();
                MapperStatement mapperStatement = configuration.getMapperStatementMap().get(statementId);
                String sql = mapperStatement.getSql();
                if (sql.startsWith("insert") || sql.startsWith("INSERT")) {
                    return add(statementId,args);
                }
                if (sql.startsWith("delete") || sql.startsWith("DELETE")) {
                    return delete(statementId,args);
                }
                if (sql.startsWith("update") || sql.startsWith("UPDATE")) {
                    return update(statementId,args);
                }
                // 判断是否进行了泛型类型参数化（返回类型是否是泛型如果是泛型则返回list如果不是则返回单个实体）
                if (genericReturnType instanceof ParameterizedType) {
                    return selectList(statementId, args);
                }
                return selectOne(statementId, args);
            }
        });
        return o;// 返回代理对象，代理对象调用接口里面的任意方法，都会执行invoke方法
    }

}
